#include <QInputDialog>
#include <QMessageBox>
#include "MainWindow.h"
#include "ui_MainWindow.h"

/**
 * 构造方法。
 * @param parent  父窗口
 */
MainWindow::MainWindow(QWidget* parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    mGameBoard(this, 0, 0, Const::GAME_BOARD_WIDTH, Const::GAME_BOARD_HEIGHT),
    mRivalWindow(this) {
    ui->setupUi(this);

    // 调整游戏区域位置
    mGameBoard.move(0, ui->menuBar->height());

    // 设置状态栏
    int labelWidth = QMainWindow::width();
    ui->statusBar->addWidget(&mLabelRivalName, labelWidth);
    mLabelRivalName.setText(tr("IDS_CURRENT_RIVAL"));

    // 创建游戏
    try {
        mGame = new Game(mGameBoard.getBitmap(), &mGameBoard);
    } catch (int) {
        QMessageBox::information(this, " ", tr("IDS_NETWORK_ERROR"));
        exit(0);
    }

    // 连接信号与槽
    QMainWindow::connect(mGame, SIGNAL(UM_GAME_OVER(GameOverReason)), SLOT(onGameOver(GameOverReason)));
    QMainWindow::connect(mGame, SIGNAL(UM_GAME_START(const char*)), SLOT(onGameStart(const char*)));
    QMainWindow::connect(mGame, SIGNAL(UM_GET_FIND_USERS_RESULT(FindUsersResult*)), SLOT(onGetFindUsersResult(FindUsersResult*)));
    QMainWindow::connect(mGame, SIGNAL(UM_GET_INVITE_REQUEST(const char*)), SLOT(onGetInviteRequest(const char*)));
    QMainWindow::connect(mGame, SIGNAL(UM_GET_INVITE_RESULT(const char*,bool)), SLOT(onGetInviteResult(const char*,bool)));
    QMainWindow::connect(&mRivalWindow, SIGNAL(UM_GET_RIVAL_NAME(const char*)), SLOT(onGetRivalName(const char*)));
    QMainWindow::connect(mGame, SIGNAL(UM_GET_LOGON_RESULT(bool)), SLOT(onGetLogonResult(bool)));
    QMainWindow::connect(mGame, SIGNAL(UM_RIVAL_QUIT_GAME(bool,const char*)), SLOT(onRivalQuitGame(bool,const char*)));

    // 登录
    this->logon();
}

/**
 * 析构方法。
 */
MainWindow::~MainWindow() {
    delete ui;
    if (mGame != nullptr) {
        delete mGame;
    }
}

/**
 * 登录。
 */
void MainWindow::logon() {
    QInputDialog inputDialog(this);
    bool ok = false;
    QString username = inputDialog.getText(this, " ", tr("IDS_INPUT_USERNAME"), QLineEdit::Normal, "", &ok);
    if (ok) {
        if (username.length() <= GomokuProtocol::MAX_USERNAME_LEN) {
            mGame->logon(username.toStdString().c_str());
        } else {
            QMessageBox::information(this, " ", tr("IDS_CONTENT_IS_TOO_LONG"));
        }
    } else {
        delete mGame;
        exit(0);
    }
}

/**
 * 单击游戏区域事件的响应方法。
 * @param e 事件相关信息
 */
void MainWindow::mouseReleaseEvent(QMouseEvent* e) {
    if (e->button() == Qt::LeftButton) {
        QPoint point = e->pos();
        point.setY(point.y() - ui->menuBar->height());
        mGame->onGameBoardClicked(point.x(), point.y());
    }
}

/**
 * "认输"菜单项的单击响应方法。
 */
void MainWindow::on_actionDefeat_triggered() {
    mGame->defeat();
}

/**
 * "寻找其它用户"菜单项的单击响应方法。
 */
void MainWindow::on_actionFindUsers_triggered() {
    mGame->findUsers();
}

/**
 * "再来一局"菜单项的单击响应方法。
 */
void MainWindow::on_actionRestart_triggered() {
    mGame->restart();
}

/**
 * 游戏结束事件的响应方法。
 * @param reason    结束原因
 */
void MainWindow::onGameOver(GameOverReason reason) {
    // 设置菜单项
    ui->actionFindUsers->setEnabled(true);
    ui->actionDefeat->setEnabled(false);
    ui->actionRestart->setEnabled(true);

    // 显示提示信息
    switch (reason) {
        case LOST:
            QMessageBox::information(this, " ", tr("IDS_LOST"));
            break;
        case RIVAL_ADMIT:
            QMessageBox::information(this, " ", tr("IDS_RIVAL_ADMIT"));
            break;
        case SELF_ADMIT:
            QMessageBox::information(this, " ", tr("IDS_SELF_ADMIT"));
            break;
        case WON:
            QMessageBox::information(this, " ", tr("IDS_WON"));
            break;
    }
}

/**
 * 游戏开始事件的响应方法。
 * @param rivalName 对手的名字
 */
void MainWindow::onGameStart(const char* rivalName) {
    // 隐藏对手列表窗口
    mRivalWindow.hide();

    // 设置菜单项
    ui->actionFindUsers->setEnabled(false);
    ui->actionDefeat->setEnabled(true);
    ui->actionRestart->setEnabled(false);

    // 显示对手的名字
    mLabelRivalName.setText(tr("IDS_CURRENT_RIVAL") + rivalName);
}

/**
 * 得到寻找用户结果事件的响应方法。
 * @param result    结果
 */
void MainWindow::onGetFindUsersResult(FindUsersResult* result) {
    if (result->mUsernameList[0][0] != '\0') {
        mRivalWindow.setUsernameList(result->mUsernameList);
        mRivalWindow.show();
    }
}

/**
 * 得到挑战请求事件的响应方法。
 * @param rivalName 对手的名字
 * @return 总是零
 */
void MainWindow::onGetInviteRequest(const char* rivalName) {
    QString question(rivalName);
    question += tr("IDS_INVITE");
    bool accept = QMessageBox::question(this, " ", question) == QMessageBox::Yes;
    mGame->acceptInvite(rivalName, accept);
}

/**
 * 得到挑战结果事件的响应方法。
 * @param rivalName 对手的名字
 * @param accept    接受挑战则为 true，否则为 false
 * @return 总是零
 */
void MainWindow::onGetInviteResult(const char* rivalName, bool accept) {
    QString information(rivalName);
    if (accept) {
        information += tr("IDS_ACCEPT");
    } else {
        information += tr("IDS_REFUSE");
    }
    QMessageBox::information(this, " ", information);
}

/**
 * 得到登录结果事件的响应方法。
 * @param succeeded 登录结果
 * @return 总是零
 */
void MainWindow::onGetLogonResult(bool succeeded) {
    if (succeeded) {
        QMessageBox::information(this, " ", tr("IDS_LOGON_SUCCEEDED"));
    } else {
        QMessageBox::information(this, " ", tr("IDS_LOGON_FAILED"));
        this->logon();
    }
}

/**
 * 获取对手的名字事件的响应方法。
 * @param rivalName 对手的名字
 */
void MainWindow::onGetRivalName(const char* rivalName) {
    mGame->invite(rivalName);
}

/**
 * 对手退出游戏事件的响应方法。
 * @param escape    对手逃跑则为 true，正常退出则为 false
 * @param rivalName 对手的名字
 */
void MainWindow::onRivalQuitGame(bool escape, const char* rivalName) {
    // 设置菜单项
    ui->actionFindUsers->setEnabled(true);
    ui->actionDefeat->setEnabled(false);
    ui->actionRestart->setEnabled(false);

    // 设置状态栏
    mLabelRivalName.setText(tr("IDS_CURRENT_RIVAL"));

    // 显示提示信息
    QString information = rivalName;
    if (escape) {
        information += tr("IDS_RIVAL_ESCAPE");
    } else {
        information += tr("IDS_RIVAL_QUIT");
    }
    QMessageBox::information(this, " ", information);
}
